package ivan
{
	/**
	 * ...
	 * @author Babel Games
	 */
	
	import fl.motion.MatrixTransformer;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.events.*
	import brwarner.GridEvent;
	import brwarner.game.GameConstants;
	import assets.Assets;
 
	public class Grid extends Sprite
	{
		private var tileSheet:Bitmap = new Assets.Tileset();
		private const tileSize:int = int(40 * 10 / GameConstants.GRID_SIZE);
		
		var _sprite:SpriteSheet;
		var _tiles:Array = new Array();
		
		//The arrow sprite
		private var _arrow:Bitmap;
		private var _arrowScale:Matrix, _arrowTranslate:Matrix, _arrowRotate:Matrix, _arrowAnchor:Matrix;
		
		//Arrow direction
		private var _arrowVisible:Boolean = false;
		
		private var _size;
		
		//Last square hovered
		private var _last:Point = new Point( -1, -1);
		
		
		private function createArrowMatrix( ):void
		{
			//Reset transform
			var m:Matrix = new Matrix();
			
			//Create new matrix
			m.concat( _arrowScale );
			m.concat( _arrowAnchor );
			m.concat( _arrowRotate );
			m.concat( _arrowTranslate );
			_arrow.transform.matrix = m;
		}
		
		
		
		private function onRollOverHandler(myEvent:MouseEvent):void {
			//Get point in question
			var p:Point = clipToGrid( myEvent.target as MovieClip );
			_last = p;
			
			//Handle alpha stuff
			dispatchEvent( new GridEvent( GridEvent.GRID_NEED_ALPHA, p.x, p.y ) );
			
			//Handle arrow
			if ( _arrowVisible ) {
				//Set arrow position
				_arrow.visible = true;
				_arrowTranslate = new Matrix();
				_arrowTranslate.translate( gridToLocal( p ).x, gridToLocal( p ).y );
				createArrowMatrix();
			}
		}
		
		private function resetOpacity():void {
			for ( var i = 0; i < _tiles.length; i++ ) {
				_tiles[i].alpha = 1;
				_tiles[i].filters = [];
			}
		}
		
		private function onRollOutHandler(myEvent:MouseEvent):void{
			resetOpacity();
			_arrow.visible = false;
			_last = new Point( -1, -1);
		}
		
		public function set ArrowVisible( v:Boolean ):void {
			_arrowVisible = v;
		}
		public function set ArrowDirection( d:Number ):void {
			_arrowRotate = new Matrix();
			_arrowRotate.rotate( Math.PI / 4 * d );
			createArrowMatrix();
			
			//Handle alpha stuff
			if( _last.x != -1 )
				dispatchEvent( new GridEvent( GridEvent.GRID_NEED_ALPHA, _last.x, _last.y ) );
		}
		
		private function onPressHandler(myEvent:MouseEvent):void{
			//Get tile information
			var c:Number = myEvent.target.name;
			
			var x:Number = c % _size;
			var y:Number = int(c / _size);
			
			//Create event
			dispatchEvent( new GridEvent(GridEvent.GRID_CLICK, y, x) );
		}
		
		//Dras a tile in the specified square
		public function setTile( tile:Point, type:Number )
		{
			(getTile(tile).getChildAt(0) as Bitmap).bitmapData = _sprite.drawTile(type);
		}
		
		private function getTile( tile:Point ) : MovieClip
		{
			return _tiles[tile.y + tile.x * _size] as MovieClip;
		}
		
		public function setOpacityGrid( tiles:Array, red:Boolean = false ) :void
		{
			resetOpacity();
			for ( var i = 0; i < tiles.length; i++ ) {
				getTile( tiles[i] as Point ).alpha = 0.8;
				if ( red )
					getTile( tiles[i] as Point ).filters = [ new GlowFilter( 0xFF0000, 1, 20, 20, 2, 1, true ) ];
			}
		}
		
		//Sets the infection of the tile
		public function setInfected( tile:Point, i:Boolean )
		{
			if ( i ) {
				//getTile(tile).filters = [ new GlowFilter( 0, 1, 25, 25, 2, 1, true, false ) ];
			}
			//else getTile(tile).filters = [ ];
		}
		
		//Converts a grid position to a local pixel location
		public function gridToLocal( grid:Point ) : Point
		{
			return new Point( grid.x * tileSize + tileSize / 2, grid.y * tileSize + tileSize / 2 );
		}
		public function clipToGrid( n:MovieClip ) : Point
		{
			var c:Number = int(n.name);
			return new Point( int(c / _size), c % _size );
		}
		
		public function Grid( s:Number )
		{
			_size = s;
			_sprite = new SpriteSheet(tileSheet, 30, 30);
			var c:int = 0;
			for (var a:int = 0; a < _size; a++ ) {
				for (var b:int = 0; b < _size; b++ ) {
					var ts:Bitmap = new Assets.Tileset();
					ts.bitmapData = _sprite.drawTile(1);
					_tiles.push(new MovieClip());
					_tiles[c].addChild(ts);
					_tiles[c].width = tileSize;
					_tiles[c].height = tileSize;
					_tiles[c].addEventListener(MouseEvent.ROLL_OVER, onRollOverHandler);
					_tiles[c].addEventListener(MouseEvent.ROLL_OUT, onRollOutHandler);
					_tiles[c].addEventListener(MouseEvent.MOUSE_DOWN, onPressHandler);
					(_tiles[c] as MovieClip).name = c.toString();
					_tiles[c].x = a * tileSize;
					_tiles[c].y = b * tileSize;
					addChild(_tiles[c]);
					c++;
				}
			}
			
			//Create the arrow
			_arrow = new Assets.Arrow();
			_arrow.visible = false;
			
			//Initial matricies
			_arrowAnchor = new Matrix();
			_arrowAnchor.translate( -tileSize / 2, -tileSize / 2 );
			_arrowScale = new Matrix();
			_arrowScale.scale( tileSize / _arrow.width, tileSize / _arrow.height );
			_arrowTranslate = new Matrix();
			_arrowRotate = new Matrix();
			addChild(_arrow);
			createArrowMatrix();
		}
		
	}

}